package org.folio.rest.impl;


import cn.hutool.core.util.StrUtil;
import io.vertx.core.AsyncResult;
import io.vertx.core.Context;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import org.folio.rest.impl.other.PartyLogSave;
import org.folio.rest.impl.other.PartyUtil;
import org.folio.rest.jaxrs.model.Errors;
import org.folio.rest.jaxrs.model.PropertyCollection;
import org.folio.rest.jaxrs.model.PropertyGroup;
import org.folio.rest.jaxrs.resource.PartyProperty;
import org.folio.rest.persist.PgUtil;
import org.folio.rest.persist.PostgresClient;
import org.folio.rest.persist.cql.CQLWrapper;
import org.folio.rest.tools.utils.ValidationHelper;

import javax.ws.rs.core.Response;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import static io.vertx.core.Future.succeededFuture;

/**
 * @author lee
 * @Classname PropertyImpl
 * @Description TODO
 * @Date 2020/6/18 16:41
 * @Created by lee
 */
public class PropertyImpl implements PartyProperty {
    private final Logger logger = LoggerFactory.getLogger("modparty");

    private static final String NOTIFY_TABLE = "property";

    @Override
    public void postPartyProperty(String lang, org.folio.rest.jaxrs.model.Property entity,
                                  Map<String, String> okapiHeaders,
                                  Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {

        String id = entity.getId();
        if (StrUtil.isBlankOrUndefined(id)) {
            id = UUID.randomUUID().toString();
        }
        //使用folio项目封装好的 数据库连接工具类 初始化当前数据库会话
        PostgresClient postgresClient = PgUtil.postgresClient(vertxContext, okapiHeaders);
        //调用对应的保存方法 持久化对到数据库
        postgresClient.save(NOTIFY_TABLE, id, entity, reply -> {
            if (reply.succeeded()){
                String ret = reply.result();
                entity.setId(ret);
                //持久化成功 通知调用方
                asyncResultHandler.handle(succeededFuture(PostPartyPropertyResponse
                        .respond201WithApplicationJson(entity, PostPartyPropertyResponse.
                                headersFor201())));
                //保存操作日志
                PartyLogSave.saveLog("新增名称为【" + entity.getName() + "】的分类",
                        2, entity.getMetadata(),entity.getOperator(), okapiHeaders, asyncResultHandler, postgresClient);
            }else{
                //持久化 出现异常情况到处理
                ValidationHelper.handleError(reply.cause(),asyncResultHandler);
            }


        });


    }


    @Override
    public void getPartyProperty(String query, int offset, int limit,
                                 String lang, Map<String, String> okapiHeaders,
                                 Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        CQLWrapper cql = null;
        try {
            // 将查询条件语句转换成适合数据库查询的CQL 语句，并返回 CQL 对象
            cql = PartyUtil.getCQL(query, limit, offset, NOTIFY_TABLE);

        } catch (Exception e) {
            //查询条件转换可能出现的异常处理
            ValidationHelper.handleError(e, asyncResultHandler);
            return;
        }
        //初始化数据库连接，并调用其中的 Get 方法 异步进行查询操作
        PgUtil.postgresClient(vertxContext, okapiHeaders)
                .get(NOTIFY_TABLE, org.folio.rest.jaxrs.model.PropertyGroup.class, new String[]{"*"}, cql,
                        true, false,
                        reply -> {
                            if (reply.succeeded()) {
                                //将查询结果存放到使用RMB框架构建生成的对象中
                                PropertyCollection notes = new PropertyCollection();
                                List<PropertyGroup> propertyGroupList
                                        = reply.result().getResults();
                                notes.setPropertyGroup(propertyGroupList);
                                Integer totalRecords = reply.result().getResultInfo().getTotalRecords();
                                notes.setTotalRecords(totalRecords);
                                //异步通知调用方，同样使用标准化构建的对象方法进行通知
                                asyncResultHandler.handle(Future.succeededFuture(
                                        GetPartyPropertyResponse.respond200WithApplicationJson(notes)));
                            } else {
                                ValidationHelper.handleError(reply.cause(), asyncResultHandler);
                            }
                        });
    }


    @Override
    public void getPartyPropertyById(String id, String lang,
                                     Map<String, String> okapiHeaders,
                                     Handler<AsyncResult<Response>> asyncResultHandler,
                                     Context vertxContext) {
        String noteId = id;
        //编号Id 为空的处理
        if (StrUtil.isBlankOrUndefined(noteId)) {
            logger.error("The id  is null , check your request id");
            Errors valErr = ValidationHelper.createValidationErrorMessage("id", noteId,
                    "Your request Id is empty, this is not allowed  ");
            asyncResultHandler.handle(succeededFuture(PutPartyPropertyByIdResponse.respond404WithTextPlain(valErr)));
            return;
        }
       //根据编号ID 获取一条数据
        PgUtil.postgresClient(vertxContext, okapiHeaders)
                .getById(NOTIFY_TABLE, id, org.folio.rest.jaxrs.model.Property.class, callback -> {
                    //获取错误的处理
                    if (callback.failed()) {
                        ValidationHelper.handleError(callback.cause(), asyncResultHandler);
                        return;
                    }
                    //数据不存在处理
                    if (callback.result() == null) {
                        asyncResultHandler.handle(Future.succeededFuture(GetPartyPropertyByIdResponse.respond404WithTextPlain(id)));
                        return;
                    }
                    //通知调用方
                    asyncResultHandler.handle(Future.succeededFuture(GetPartyPropertyByIdResponse.
                            respond200WithApplicationJson(callback.result())));
                });
    }


    @Override
    public void deletePartyPropertyById(String id, String lang,
                                        Map<String, String> okapiHeaders,
                                        Handler<AsyncResult<Response>> asyncResultHandler,
                                        Context vertxContext) {
        String noteId = id;
        if (StrUtil.isBlankOrUndefined(noteId)) {
            logger.error("The id  is null , check your request id");
            Errors valErr = ValidationHelper.createValidationErrorMessage("id", noteId,
                    "Your request id is empty, this is not allowed  ");
            asyncResultHandler.handle(succeededFuture(PutPartyPropertyByIdResponse.respond404WithTextPlain(valErr)));
            return;
        }
        PostgresClient postgresClient = PgUtil.postgresClient(vertxContext, okapiHeaders);
        //根据该编号查询该数据，如果数据存在，那么执行伪删除
        postgresClient.getById(NOTIFY_TABLE, id, org.folio.rest.jaxrs.model.Property.class, callback -> {
            if (callback.failed()) {
                ValidationHelper.handleError(callback.cause(), asyncResultHandler);
                return;
            }
            if (callback.result() == null) {
                asyncResultHandler.handle(succeededFuture(PutPartyPropertyByIdResponse.respond404WithTextPlain(id)));
                return;
            }
            org.folio.rest.jaxrs.model.Property object = callback.result();
            postgresClient.delete(NOTIFY_TABLE,object.getId(),replyDel->{
                if (replyDel.succeeded()){
                    if (replyDel.result().getUpdated() == 0) {
                         asyncResultHandler.handle(succeededFuture(DeletePartyPropertyByIdResponse
                                 .respond404WithTextPlain(id)));
                   } else {
                         asyncResultHandler.handle(Future.succeededFuture(
                                DeletePartyPropertyByIdResponse.respond204()));

                         PartyLogSave.saveLog("删除编号为【" + id + "】的分类", 4,
                                 null, okapiHeaders, asyncResultHandler, postgresClient);
                    }
                }else{
                    ValidationHelper.handleError(replyDel.cause(), asyncResultHandler);
                }
            });
 
        });
    }

    @Override
    public void putPartyPropertyById(String id, String lang, org.folio.rest.jaxrs.model.Property entity,
                                     Map<String, String> okapiHeaders,
                                     Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
        final String noteId = id;
        if (StrUtil.isBlankOrUndefined(noteId)) {
            logger.error("The id  is null , check your request id");
            Errors valErr = ValidationHelper.createValidationErrorMessage("id", noteId,
                    "Your request id is empty, this is not allowed  ");
            asyncResultHandler.handle(succeededFuture(PutPartyPropertyByIdResponse.respond404WithTextPlain(valErr)));
            return;
        }
        //
        PostgresClient postgresClient = PgUtil.postgresClient(vertxContext, okapiHeaders);
            postgresClient.update(NOTIFY_TABLE, entity, entity.getId(), reply2 -> {
                if (reply2.succeeded()) {
                    //如果更新条数为0 则告诉调用方
                    if (reply2.result().getUpdated() == 0) {
                        asyncResultHandler.handle(Future.succeededFuture(PostPartyPropertyResponse.respond401WithTextPlain(entity)
                        ));
                    } else {
                        //更新成功的通知
                        asyncResultHandler.handle(Future.succeededFuture(PostPartyPropertyResponse
                                .respond201WithApplicationJson(entity, PostPartyPropertyResponse.
                                        headersFor201())));
                        //保存操作日志
                        PartyLogSave.saveLog("更新名称为【" + entity.getName() + "】的分类",
                                3, entity.getMetadata(),entity.getOperator(), okapiHeaders, asyncResultHandler, postgresClient);
                    }
                } else {
                    ValidationHelper.handleError(reply2.cause(), asyncResultHandler);
                }
            });



    }
}
